<template>
    <el-dialog
      :title="title"
      v-model="visibleInner"
      :width="width"
      append-to-body
      @open="onOpen"
    >
      <div class="mb8" style="display:flex;gap:8px;align-items:center">
        <el-button type="primary" plain @click="addRow()">新增一行</el-button>
        <slot name="tip">
          <el-alert
            type="info"
            :closable="false"
            show-icon
            description="同一编码(code)将合并为一个备件(asset_spare)，行内的 规格(spec)/厂商(vendor)转为该备件的多个规格(asset_spare_variant)。"
          />
        </slot>
      </div>
  
      <el-table :data="rows" border stripe :height="tableHeight">
        <!-- spare 维度 -->
        <el-table-column label="编码(code)" min-width="140">
          <template #default="{row}">
            <el-input v-model="row.code" placeholder="必填" />
          </template>
        </el-table-column>
        <el-table-column label="名称(name)" min-width="180">
          <template #default="{row}">
            <el-input v-model="row.name" placeholder="必填" />
          </template>
        </el-table-column>
        <el-table-column label="单位(unit)" width="120">
          <template #default="{row}">
            <el-select v-model="row.unit">
              <el-option v-for="u in unitOptionsInner" :key="u.value" :label="u.label" :value="u.value" />
            </el-select>
          </template>
        </el-table-column>
        <el-table-column label="总库存" width="110" align="center">
          <template #default="{row}">
            <el-input-number v-model="row.stockTotal" :min="0" :step="1" controls-position="right" />
          </template>
        </el-table-column>
        <el-table-column label="在线库存" width="110" align="center">
          <template #default="{row}">
            <el-input-number v-model="row.stockAvailable" :min="0" :step="1" controls-position="right" />
          </template>
        </el-table-column>
        <el-table-column label="类型" width="120">
          <template #default="{row}">
            <el-select v-model="row.type">
              <el-option v-for="o in typeOptionsInner" :key="o.value" :label="o.label" :value="o.value" />
            </el-select>
          </template>
        </el-table-column>
        <el-table-column label="状态" width="120">
          <template #default="{row}">
            <el-select v-model="row.status">
              <el-option v-for="o in statusOptionsInner" :key="o.value" :label="o.label" :value="o.value" />
            </el-select>
          </template>
        </el-table-column>
        <el-table-column label="计划日期" width="150">
          <template #default="{row}">
            <el-date-picker v-model="row.planDate" type="date" value-format="YYYY-MM-DD" placeholder="选择日期" />
          </template>
        </el-table-column>
        <el-table-column label="采购日期" width="150">
          <template #default="{row}">
            <el-date-picker v-model="row.orderDate" type="date" value-format="YYYY-MM-DD" placeholder="选择日期" />
          </template>
        </el-table-column>
        <el-table-column label="备注" min-width="160">
          <template #default="{row}">
            <el-input v-model="row.remark" placeholder="备注" />
          </template>
        </el-table-column>
  
        <!-- variant 维度 -->
        <el-table-column label="规格(spec)" min-width="160">
          <template #default="{row}">
            <el-input v-model="row.spec" placeholder="如：DN65×DN50 / 6204-2RS" />
          </template>
        </el-table-column>
        <el-table-column label="厂商(vendor)" min-width="160">
          <template #default="{row}">
            <el-input v-model="row.vendor" placeholder="品牌或供应商" />
          </template>
        </el-table-column>
  
        <el-table-column label="操作" width="160" fixed="right" align="center">
          <template #default="{row, $index}">
            <el-button link type="primary" @click="copyRow(row,$index)">复制一层</el-button>
            <el-button link type="danger"  @click="removeRow($index)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>
  
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="close">取 消</el-button>
          <el-button type="primary" :loading="submitting" @click="submit">提 交</el-button>
        </div>
      </template>
    </el-dialog>
  </template>
  
  <script setup>
  import { ref, computed } from 'vue'
  import { ElMessage } from 'element-plus'
  
  defineOptions({ name: 'SpareBatchEditor' })
  
  /** Props */
  const props = defineProps({
    visible: { type: Boolean, default: false },
    title: { type: String, default: '批量新增备件' },
    width: { type: String, default: '1200px' },
    tableHeight: { type: [Number, String], default: '60vh' },
    unitOptions: { type: Array, default: () => ['个','台','套','米','公斤'].map(v => ({ label: v, value: v })) },
    statusOptions: { type: Array, default: () => [{ label: '启用', value: 0 }, { label: '停用', value: 1 }] },
    typeOptions: { type: Array, default: () => [{ label: '普通', value: 0 }, { label: '特殊备件', value: 1 }] },
    initialRows: { type: Array, default: () => [] },
    submitting: { type: Boolean, default: false }
  })
  
  /** Emits */
  const emit = defineEmits(['update:visible', 'submit', 'open'])
  
  /** v-model 代理 */
  const visibleInner = computed({
    get: () => props.visible,
    set: (v) => emit('update:visible', v)
  })
  
  /** 选项内部代理 */
  const unitOptionsInner = computed(() => props.unitOptions)
  const statusOptionsInner = computed(() => props.statusOptions)
  const typeOptionsInner = computed(() => props.typeOptions)
  
  /** 行数据 */
  const rows = ref([])
  
  /** 打开时初始化 */
  function onOpen () {
    if (props.initialRows?.length) {
      rows.value = normalizeInitRows(props.initialRows)
    } else if (!rows.value.length) {
      rows.value = [newRow()]
    }
    emit('open')
  }
  
  function newRow () {
    return {
      uid: Date.now() + Math.random(),
      code: '',
      name: '',
      unit: unitOptionsInner.value?.[0]?.value ?? '个',
      stockTotal: 0,
      stockAvailable: 0,
      type: 0,
      status: 0,
      remark: '',
      planDate: null,
      orderDate: null,
      spec: '',
      vendor: ''
    }
  }
  function normalizeInitRows (list) {
    return (list || []).map(r => ({
      uid: Date.now() + Math.random(),
      code: r.code ?? '',
      name: r.name ?? '',
      unit: r.unit ?? (unitOptionsInner.value?.[0]?.value ?? '个'),
      stockTotal: Number(r.stockTotal ?? 0),
      stockAvailable: Number(r.stockAvailable ?? 0),
      type: Number(r.type ?? 0),
      status: Number(r.status ?? 0),
      remark: r.remark ?? '',
      planDate: r.planDate ?? null,
      orderDate: r.orderDate ?? null,
      spec: r.spec ?? '',
      vendor: r.vendor ?? ''
    }))
  }
  
  /** 行操作 */
  function addRow (afterIndex) {
    if (typeof afterIndex === 'number') rows.value.splice(afterIndex + 1, 0, newRow())
    else rows.value.push(newRow())
  }
  function copyRow (row, index) {
    const c = JSON.parse(JSON.stringify(row))
    c.uid = Date.now() + Math.random()
    rows.value.splice(index + 1, 0, c)
  }
  function removeRow (index) {
    rows.value.splice(index, 1)
    if (!rows.value.length) rows.value.push(newRow())
  }
  
  /** 校验与组装 */
  function validateRows () {
    const list = rows.value
    if (!list.length) return '请至少添加一行数据'
    for (let i = 0; i < list.length; i++) {
      const r = list[i]
      if (!r.code?.trim()) return `第 ${i + 1} 行：编码不能为空`
      if (!r.name?.trim()) return `第 ${i + 1} 行：名称不能为空`
      const t = Number(r.stockTotal); const a = Number(r.stockAvailable)
      if (isNaN(t) || t < 0) return `第 ${i + 1} 行：总库存需为非负数字`
      if (isNaN(a) || a < 0) return `第 ${i + 1} 行：在线库存需为非负数字`
      if (a > t) return `第 ${i + 1} 行：在线库存不可大于总库存`
    }
    const nameByCode = new Map()
    for (const r of list) {
      const k = r.code.trim()
      if (!nameByCode.has(k)) nameByCode.set(k, r.name.trim())
      else if (nameByCode.get(k) !== r.name.trim()) return `编码 ${k} 的“名称”不一致，请检查`
    }
    return null
  }
  
  function buildPayload () {
    const groups = new Map()
    for (const r of rows.value) {
      const key = r.code.trim()
      if (!groups.has(key)) {
        groups.set(key, {
          code: key,
          name: r.name.trim(),
          unit: r.unit || '个',
          stockTotal: Number(r.stockTotal) || 0,
          stockAvailable: Number(r.stockAvailable) || 0,
          type: Number(r.type) || 0,
          status: Number(r.status) || 0,
          remark: r.remark?.trim() || '',
          planDate: r.planDate || null,
          orderDate: r.orderDate || null,
          variants: []
        })
      }
      if (r.spec?.trim() || r.vendor?.trim()) {
        const g = groups.get(key)
        if (!g.variants.some(v => v.spec === r.spec?.trim() && v.vendor === r.vendor?.trim())) {
          g.variants.push({
            spec: r.spec?.trim() || '',
            vendor: r.vendor?.trim() || '',
            status: Number(r.status) || 0
          })
        }
      }
    }
    return Array.from(groups.values())
  }
  
  function submit () {
    const msg = validateRows()
    if (msg) {
      ElMessage.warning(msg)
    } else {
      const payload = buildPayload()
      if (!payload.length) ElMessage.warning('没有可提交的数据')
      else emit('submit', payload)
    }
  }
  
  /** 控制方法暴露 */
  function open () { visibleInner.value = true }
  function close () { visibleInner.value = false }
  function setRows (list) { rows.value = normalizeInitRows(list) }
  function getRows () { return rows.value.slice() }
  defineExpose({ open, close, addRow, copyRow, removeRow, setRows, getRows })
  </script>
  
  <style scoped>
  .mb8 { margin-bottom: 8px; }
  </style>
  